#!/usr/bin/env python3

# Copyright 2019 The Kapitan Authors
# SPDX-FileCopyrightText: 2020 The Kapitan Authors <kapitan-admins@googlegroups.com>
#
# SPDX-License-Identifier: Apache-2.0

"external input tests"

import os
import random
import string
import subprocess
import sys
import tempfile
import unittest

from kapitan.cached import reset_cache
from kapitan.cli import main
from kapitan.inputs.external import External
from kapitan.inventory.model.input_types import KapitanInputTypeExternalConfig


class ExternalInputTest(unittest.TestCase):
    def setUp(self):
        os.chdir(os.path.join("tests", "test_resources"))

    def test_compile(self):
        temp = tempfile.mkdtemp()
        sys.argv = ["kapitan", "compile", "--output-path", temp, "-t", "external-test"]
        main()
        self.assertTrue(
            os.path.isfile(
                os.path.join(
                    temp,
                    "compiled",
                    "external-test",
                    "test.md",
                )
            )
        )

    def test_compile_file(self):
        # tests setting of args, env_vars and "\${compiled_target_dir}" being properly substituted
        external_script_content = """
        #!/usr/bin/env bash
        set -ex

        name=$1
        compiled_target_dir=$2

        echo "test-${NAME}" > "${compiled_target_dir}/${name}"
        """
        compile_path = tempfile.mkdtemp()
        temp_dir = tempfile.mkdtemp()
        external_script_file_path = os.path.join(temp_dir, "script.sh")
        with open(external_script_file_path, "w") as f:
            f.write(external_script_content)

        search_paths = [external_script_file_path]
        ref_controller = None
        external_compiler = External(
            compile_path, search_paths, ref_controller, "test", None
        )

        letters = string.ascii_lowercase
        name = "".join(random.choice(letters) for i in range(8))
        config = KapitanInputTypeExternalConfig(
            input_paths=[external_script_file_path],
            output_path=compile_path,
            env_vars={"NAME": name},
            args=[name, r"\${compiled_target_dir}"],
        )

        with self.assertRaises(ValueError) as e:
            external_compiler.compile_file(
                config, external_script_file_path, compile_path
            )

        self.assertTrue("Executing external input with command" in e.exception.args[0])
        self.assertTrue("failed" in e.exception.args[0])
        self.assertTrue("Permission denied" in e.exception.args[0])

        # make file executable so there's no failure
        subprocess.check_call(["chmod", "+x", external_script_file_path])
        external_compiler.compile_file(config, external_script_file_path, compile_path)

        generated_file = os.path.join(compile_path, name)
        with open(generated_file) as f:
            generated_file_content = f.readlines()[0]
        self.assertTrue(
            os.path.isfile(generated_file),
            msg=f"File {generated_file} should be generated by compile_file",
        )
        self.assertEqual(
            generated_file_content,
            f"test-{name}\n",
            msg="Correct content should be written to file",
        )

    def tearDown(self):
        os.chdir("../../")
        reset_cache()
